#include "stdafx.h"

#include "IComponent.h"

using namespace std;

namespace ZeEngine
{
	std::map<std::string, s64> IComponent::m_componentTypes;
	std::map<std::string, s64> IComponent::m_componentIndexes;

	s64 IComponent::m_currentType = 1;
	s64 IComponent::m_currentIndex = 0;

	IComponent::IComponent(const std::string& name, s64& type, s64& index) : m_pParent(NULL)
	{
		CreateType(name);
		type = GetNextType();
		index = GetNextIndex();
	}

	IComponent::~IComponent()
	{
	}

	s64 IComponent::GetNextType()
	{
		s64 type = GetComponentType(m_componentTypes, m_name);
		if (type == -1)
		{
			//Shift bit to the left to allow up to 64 different components
			type = m_currentType;
			m_currentType = m_currentType << 1;
			m_componentTypes.insert(std::pair<const std::string&, s64>(m_name, type));
		}

		return type;
	}

	s64 IComponent::GetNextIndex()
	{
		s64 index = GetComponentType(m_componentIndexes, m_name);

		if (index == -1)
		{
			index = m_currentIndex++;
			m_componentIndexes.insert(std::pair<const std::string&, s64>(m_name, index));
		}

		return index;
	}

	void IComponent::CreateType(const std::string& name)
	{
		//Create a map of types and indexes to improve performance when searching and comparing these components
		m_name = name;
		m_type = GetComponentType(m_componentTypes, name);

		if (m_type == -1)
		{
			//Shift bit to the left to allow up to 64 different components
			m_type = m_currentType;
			m_index = m_currentIndex++;

			m_currentType = m_currentType << 1;

			m_componentTypes.insert(std::pair<const std::string&, s64>(name, m_type));
			m_componentIndexes.insert(std::pair<const std::string&, s64>(name, m_index));
		}
		else
		{
			//We found the type so lets also add the index
			m_index = GetComponentType(m_componentIndexes, name);
		}
	}


	s64 IComponent::GetAndCreateComponentType(const std::string& name)
	{
		s64 type = GetComponentType(m_componentTypes, name);
        u32 index = 0;
		if (type == -1)
		{
			//Shift bit to the left to allow up to 64 different components
			type = m_currentType;
            index = m_currentIndex;
			m_currentIndex++;
			m_currentType = m_currentType << 1;

			m_componentTypes.insert(std::pair<const std::string&, s64>(name, type));
            m_componentIndexes.insert(std::pair<const std::string&, s64>(name, index));
		}

		return type;
	}

	s64 IComponent::GetComponentType(const std::map<std::string, s64>& map, const std::string& name)
	{
		s64 type = -1;

		auto it = map.find(name);
		if (it != map.end())
		{
			type = it->second;
		}

		return type;
	}
}